#pragma once

#include <vector>
#include <string>
#include <algorithm>

class Buffer
{
public:
    static const size_t kCheapPrepend = 8;
    static const size_t kInitialSize = 1024;

    explicit Buffer(size_t initialSize = kInitialSize)
        : buffer_(kCheapPrepend+initialSize)
        , readerIndex_(kCheapPrepend)
        , writerIndex_(kCheapPrepend)
    {

    }

    size_t readableBytes() const {return writerIndex_-readerIndex_;}
    size_t writableBytes() const {return buffer_.size()-writerIndex_;}
    size_t prependableBytes() const {return readerIndex_;}

    // 返回缓冲区中可读数据的起始地址
    const char* peek() const {return begin()+readerIndex_;}

    // 从缓冲区头部回收len字节的已读数据
    // 将缓冲区中最前面的已经处理完毕的 len 字节标记为 “可复用空间”
    // 使得这部分空间未来可以被新数据覆盖
    void retrieve(size_t len)
    {
        if(len<readableBytes())
        {
            readerIndex_+=len; 
        }
        else
        {
            retrieveAll();
        }
    }

    void retrieveAll()
    {
        readerIndex_=writerIndex_=kCheapPrepend;
    }

    // 从缓冲区中读取len字节的字符串 并同时回收这部分已读数据
    std::string retrieveAsString(size_t len)
    {
        std::string ret(peek(),len);
        retrieve(len);
        return ret;
    }

    // 把onMessage函数上报的Buffer数据 转成string类型的数据返回
    std::string retrieveAllAsString()
    {
        return retrieveAsString(readableBytes());
    }

    // buffer_.size()-writerIndex_  len
    void ensureWriteableBytes(size_t len)
    {
        if(writableBytes()<len)
        {
            makeSpace(len); //扩容
        }
    }

    // 把[data,data+len]内存上的数据 添加到writeable缓冲区上
    void append(const char* data ,size_t len)
    {
        ensureWriteableBytes(len);
        std::copy(data,data+len,beginWrite());
        writerIndex_+=len;
    }

    char* beginWrite()
    {
        return begin()+writerIndex_;
    }

    const char* beginWrite() const
    {
        return begin()+writerIndex_;
    }

    // 从fd读取数据
    ssize_t readFd(int fd,int* saveErrno);
    ssize_t writeFd(int fd,int* saveErrno);
private:

    char* begin() {return &*buffer_.begin();} // vector底层数组首元素地址 即数组起始地址
    const char* begin() const {return &*buffer_.begin();}
    void makeSpace(size_t len)
    {
        if(writableBytes()+prependableBytes()<len+kCheapPrepend)
        {
            buffer_.resize(writerIndex_+len);
        }
        else
        {
            size_t readable =readableBytes();
            std::copy(begin()+readerIndex_,begin()+writerIndex_,begin()+kCheapPrepend);
            readerIndex_=kCheapPrepend;
            writerIndex_=readerIndex_+readable;
        }
    }

    std::vector<char> buffer_;
    size_t readerIndex_;
    size_t writerIndex_;
};